package com.kqzz.common.config.mapper;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import org.apache.ibatis.cache.CacheKey;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Plugin;
import org.apache.ibatis.plugin.Signature;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;

/**
 * @author lipeng
 * @Description 针对Map结构做数据脱敏和字段属性统一转小写驼峰格式
 * @ClassName DesensitizationInterceptor.java
 * @Package com.kqzz.common.config.mapper
 * @date 2022年2月28日 下午2:10:42
 * @update_Desc
 * @update_Author
 * @update_Date
 */
@Intercepts({
    @Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class,
        RowBounds.class, ResultHandler.class}),
    @Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class,
        RowBounds.class, ResultHandler.class, CacheKey.class, BoundSql.class}),})
public class DesensitizationInterceptor implements Interceptor {

  @Override
  public Object intercept(Invocation invocation) throws Throwable {
    Object result = invocation.proceed();

    // 仅对Map进行处理
    if (result instanceof Map) {
      return transformUpperCase((Map<String, Object>) result);
    }

    // 处理List<Map>集合
    if (result instanceof ArrayList<?>) {
      List<?> list = (ArrayList<?>) result;
      for (Object obj : list) {
        if (obj instanceof Map) {
          obj = transformUpperCase((Map<String, Object>) obj);
        } else {
          break;
        }
      }
      return list;
    }
    return result;
  }

  @Override
  public Object plugin(Object target) {
    // TODO Spring bean 方式配置时，如果没有配置属性就不会执行下面的 setProperties
    // 方法，就不会初始化，因此考虑在这个方法中做一次判断和初始化
    return Plugin.wrap(target, this);
  }

  /**
   * 用于在Mybatis配置文件中指定一些属性的，注册当前拦截器的时候可以设置一些属性
   */
  @Override
  public void setProperties(Properties properties) {
  }

  /**
   * @param oldMap
   * @return
   * @Descripton 大写属性转小写驼峰规则
   * @author lipeng
   * @date 2022年2月28日 上午10:34:23
   * @update_Desc
   * @update_Author
   * @update_Date
   */
  private Map<String, Object> transformUpperCase(Map<String, Object> oldMap) {
    Map<String, Object> resultMap = new HashMap<>();

    if (oldMap == null || oldMap.isEmpty()) {
      return oldMap;
    }

    Set<String> keySet = oldMap.keySet();
    for (String key : keySet) {
      String newKey = key.toLowerCase();
      String[] names = newKey.split("_");
      StringBuilder finalName = new StringBuilder();
      int i = 0;
      if (names.length == 1) {
        resultMap.put(newKey, oldMap.get(key));
      } else {
        for (; i < names.length; i++) {
          String temp = names[i];
          if (i > 0) {
            char ch = temp.charAt(0);
            ch = Character.toUpperCase(ch);
            temp = ch + temp.substring(1);
          }

          finalName.append(temp);
        }
        resultMap.put(finalName.toString(), oldMap.get(key));
      }
    }
    oldMap.clear();
    oldMap.putAll(resultMap);
    return oldMap;
  }
}
